package view.parameterpanels;

import java.awt.Component;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import model.IManufacturingMethod;
import net.miginfocom.swing.MigLayout;
import view.CenterTabbedPane.EBenchmarkTab;
import view.EBenchmarkPanel;
import view.NumericalTextField;

/**
 * The view class {@code StandardParameterInputPanel} draws a standard panel
 * that can be used for input parameters. It shows basic parameter information
 * and an input text field that allows the user to interact with the model.
 * @author Oliver Eckstein
 *
 */
public class StandardParameterInputPanel extends EBenchmarkPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * The title that gives the user a description of the panel.
	 */
	protected JLabel title;
		
	/**
	 * A JPanel where the user can setup what is shown on the panel.
	 */
	protected JPanel settings;
	
	/**
	 * The most important part of a {@code ParameterPanel}. On this panel
	 * all important parameter information is drawn.
	 */
	protected JPanel paramPanel;
	
	/**
	 * The parameter panels get stored in here.
	 */
	protected List<JPanel> parameterPanels;
	
	/**
	 * The text fields of the parameter panels.
	 */
	protected List<NumericalTextField> textFields;
	
	/**
	 * The referenced model.
	 */
	protected IManufacturingMethod manuMethod;

	/**
	 * To create a new {@code StandardParameterInputPanel}.
	 * @param logoPath a path to an optional logo that is displayed
	 * on the panel. If passed {@code null} a standard logo is used.
	 * @param tab the type of input parameters that is displayed on the panel. 
	 * @param panelTitle the panel's title.
	 * @param manuMethod the manufacturing method to be referenced.
	 */
	public StandardParameterInputPanel(
			String logoPath,
			EBenchmarkTab tab,
			String panelTitle,
			IManufacturingMethod manuMethod) {
		super(logoPath, tab);
		this.manuMethod = manuMethod;
		init();
		this.setName(panelTitle);
		setTitle(panelTitle);
		drawSettings();
	}
	
	/**
	 * To set the panel's initial conditions.
	 */
	private void init() {
		title = new JLabel();
		settings = new JPanel();
		paramPanel = new JPanel();
		paramPanel.setLayout(new MigLayout());
		parameterPanels = new ArrayList<JPanel>();
		textFields = new ArrayList<NumericalTextField>();
		
		this.setLayout(new MigLayout());
		this.add(title, "wrap");
		this.add(settings, "wrap");
		this.add(paramPanel);
		this.add(logo, "aligny top");
	}
	
	/**
	 * To set the title of this {@code ParameterPanel}.
	 * @param title the title.
	 */
	public void setTitle(String title) {
		this.title.setText(title);
		this.revalidate();
	}
	
	/**
	 * To get the {@code JPanel} on which the parameter panels gets drawn.
	 * @return the parameter panel.
	 */
	public JPanel getParameterPanel() {
		return paramPanel;
	}
	
	/**
	 * To set a new text for a bordered parameter panel.
	 * @param position the position of the parameter panel within the panel.
	 * @param text the new text.
	 */
	public void setBorderText(int position, String text) {
		parameterPanels.get(position).setBorder(BorderFactory
                .createTitledBorder(text));
		this.revalidate();
	}
	
	/**
	 * To remove a parameter set from this panel.
	 * @return the removed text fields.
	 */
	public List<JTextField> removeParameterPanel() {
		int panelsCount = parameterPanels.size() - 1;
		List<JTextField> removedTextFields = new ArrayList<JTextField>();
		
		if(panelsCount > 0) {			
			JPanel panelToRemove = parameterPanels.get(panelsCount);
			paramPanel.remove(panelToRemove);
			for(Component component : panelToRemove.getComponents()) {
				if(component instanceof JTextField) {
					removedTextFields.add((JTextField) component);
				}
			}
			textFields.removeAll(removedTextFields);
			parameterPanels.remove(panelsCount);
			this.revalidate();
		}
		return removedTextFields;
	}
	
	/**
	 * To get all numerical text fields of this {@code ParameterPanel}.
	 * @return the text fields.
	 */
	public List<NumericalTextField> getTextFields() {
		return textFields;
	}
	
	@Override
	public void update() {    
		if(getErrorStatus()) {
			// To disable all text fields because of wrong input			
			for(NumericalTextField txtField : textFields) {
				if(!txtField.getErrorStatus()) {
					txtField.setEnabled(false);
				}
			}
		} else {
			// To enable all disabled text fields when wrong input was corrected
			for(NumericalTextField txtField : textFields) {
				if(!txtField.isEnabled() && 
						manuMethod.getParameter(
								txtField.getParameterID()).isSetByUser()) {
					txtField.setEnabled(true);
				} else if(txtField.isEnabled() && 
						!manuMethod.getParameter(
								txtField.getParameterID()).isSetByUser()) {
					txtField.setEnabled(false);
				}
			}
		}		
	}
	
	/**
	 * To draw the settings panel of this {@code ParameterPanel}.
	 */
	protected void drawSettings() {
		// Nothing to do here. This method gets interesting in derived classed.
	}
	
	/**
	 * To add a parameter set to this panel.
	 * @param paramInfo the parameters' information:<br>
     * paramInfo[0] = parameter's name<br>
     * paramInfo[1] = parameter's key for identification<br>
     * paramInfo[2] = parameter's abbreviation<br>
     * paramInfo[3] = parameter's unit<br>
     * paramInfo[4] = parameter's initial value.
     * @param borderTitle the parameters' description.
	 * @return The newly created text fields.
	 */
	protected List<JTextField> addStandardParameterPanels(
			JPanel parameterPanel,
			List<String[]> paramInfo,
			String borderTitle){
		List<JTextField> newTextFields = new ArrayList<JTextField>();
		parameterPanel.setBorder(BorderFactory
                .createTitledBorder(borderTitle));
		for(String[] param : paramInfo) {
        	parameterPanel.add(new JLabel(param[0]));
            parameterPanel.add(new JLabel(param[2]));
            parameterPanel.add(new JLabel(param[3]));                
            
            NumericalTextField valueTF = new NumericalTextField(param[1]);
            valueTF.setText(param[4]);           
            parameterPanel.add(valueTF);
            textFields.add(valueTF);  
            newTextFields.add(valueTF);            
        }
		parameterPanels.add(parameterPanel);
        paramPanel.add(parameterPanel, "wrap");
        return newTextFields;		
	}
	
	/**
	 * To get the input parameter panels of this panel.
	 * @return The input parameter panels.
	 */
	public List<JPanel> getparameterPanels() {
		return parameterPanels;
	}
	
	/**
	 * To add a geometry set to this panel.
	 * @param paramInfo the parameters' information:<br>
     * paramInfo[0] = parameter's name<br>
     * paramInfo[1] = parameter's key for identification<br>
     * paramInfo[2] = parameter's abbreviation<br>
     * paramInfo[3] = parameter's unit<br>
     * paramInfo[4] = parameter's initial value
     * @param borderTitle the parameters' description.
     * @return The newly created text fields.
     */
	public List<JTextField> addParameterSet(List<String[]> paramInfo,
			String borderTitle) {
		List<JTextField> newTextFields = new ArrayList<JTextField>();
		JPanel parameterPanel = new JPanel();
    	parameterPanel.setLayout(new MigLayout("wrap 4"));
    	newTextFields.addAll(
        		addStandardParameterPanels(
        				parameterPanel, paramInfo, borderTitle));
    	return newTextFields;
	}

}
